﻿#include "guild_service_timer_context.h"

#include "guildservicetimer/LoginArg_struct.h"
#include "guildservicetimer/LoginRes_struct.h"
#include "guildservicetimer/LogoutNtfData_struct.h"
#include "guildservicetimer/GuildBuildingUpgradeArg_struct.h"
#include "guildservicetimer/GuildBuildingUpgradeRes_struct.h"

#include "token/service_token_mgr.hpp"
#include "proxy/guild_service_timer_proxy_mgr.h"
#include "timer/service_timer_mgr.hpp"

#include "guild/guild.h"
#include "box/service_context.hh"
#include "error/make_error_code.h"
#include "fwd.h"

#include "logic/guild_building_logic.h"

#include "timer/guild_auction_timer.h"
#include "timer/guild_refresh_timer.h"

namespace guild_service {

bool GuildServiceTimerContext::Start(kratos::service::ServiceContext *context) {
  if (!GuildServiceTimerContext::Init(context)) {
    LOG_FAIL("公会定时服务启动失败");
    return false;
  }

  return register_service(std::string(kGuildServicePrefix) + std::string(kGuildServiceTimerName));
}

bool GuildServiceTimerContext::Stop() {
  LOG_INFO("公会定时服务关闭");

  if (!unregister_service(std::string(kGuildServicePrefix) +
                          std::string(kGuildServiceTimerName))) {
    LOG_FAIL("公会定时服务关闭失败");
    return false;
  }

  return GuildServiceTimerContext::Uninit();
}

bool GuildServiceTimerContext::Init(kratos::service::ServiceContext *context) {
  if (!common::singleton_start<common::service_logger>(
          context, kGuildServiceTimerName)) {
    return false;
  }

  LOG_INFO("公会定时服务启动");

  if (!common::singleton_start<common::service_context>(context)) {
    LOG_FAIL("公会定时服务启动失败");
    return false;
  }

  if (!common::singleton_start<common::service_redis_client>(context)) {
    LOG_FAIL("公会定时服务启动失败");
    return false;
  }

  std::string redis_host(kRedisHost);
  int32_t redis_port = kRedisPort;
  std::string redis_user(kRedisUser);
  std::string redis_passwd(kRedisPasswd);

  {// config.redis
    auto* config_ptr = ServiceContextSingleton()->get_config().get_config_ptr();
    if (!config_ptr) {
      LOG_FAIL("公会定时服务启动失败");
      return false;
    }
    if (config_ptr->has("redis")) {
      if (config_ptr->has("redis.host")) {
        redis_host = config_ptr->getString("redis.host");
      }
      if (config_ptr->has("redis.port")) {
        redis_port = config_ptr->getInt32("redis.port");
      }
      if (config_ptr->has("redis.user")) {
        redis_user = config_ptr->getString("redis.user");
      }
      if (config_ptr->has("redis.passwd")) {
        redis_passwd = config_ptr->getString("redis.passwd");
      }
    }
  }

  if (!redis_add_host(kGuildServiceTimerName, redis_host, redis_port,
                      redis_user, redis_passwd)) {
    LOG_FAIL("公会定时服务启动失败");
    return false;
  }

  if (!common::singleton_start<common::util>(context)) {
    LOG_FAIL("公会定时服务启动失败");
    return false;
  }

  if (!common::singleton_start<common::service_time_scheduler>(context)) {
    LOG_FAIL("公会定时服务启动失败");
    return false;
  }
  
  if (!common::singleton_start<GuildAuctionTimer>()) {
    LOG_FAIL("公会定时服务启动失败");
    return false;
  }
  
  if (!common::singleton_start<GuildAuctionTimer>()) {
    LOG_FAIL("公会定时服务启动失败");
    return false;
  }

  if (!common::singleton_start<GuildRefreshTimer>()) {
    LOG_FAIL("公会定时服务启动失败");
    return false;
  }

  return true;
}

bool GuildServiceTimerContext::Uninit() {
  return common::singleton_stop<GuildRefreshTimer>() &&
         common::singleton_stop<GuildAuctionTimer>() &&
         common::singleton_stop<common::service_time_scheduler>() &&
         common::singleton_stop<common::service_redis_client>() &&
         common::singleton_stop<common::util>() &&
         common::singleton_stop<common::service_context>() &&
         common::singleton_stop<common::service_logger>();

  return true;
}

void GuildServiceTimerContext::Tick(time_t ms) {
  common::singleton_update<common::service_redis_client>(ms);
  common::singleton_update<common::service_time_scheduler>(ms);
  GuildServiceTimerProxyMgrSingleton->RemoveNotConnectedProxy();
  ServiceTimerMgrSingleton().clear_invalid_timer();
}

void GuildServiceTimerContext::Login(
    rpc::StubCallPtr call, const LoginArg &arg,
    const std::shared_ptr<LoginRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceTimerName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }

  if (!GuildServiceTimerProxyMgrSingleton->Login(call, role_uuid)) {
    res->result = ErrorCode::ERR_FAILED;
    return;
  }

  res->result = ErrorCode::ERR_SUCCESS;
}

void GuildServiceTimerContext::Logout(rpc::StubCallPtr call, const LogoutNtfData &data) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = data.token;
#endif

  if (token == kInvalidToken) {
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceTimerName, token);
  if (role_uuid == kInvalidRoleUuid) {
    return;
  }

  GuildServiceTimerProxyMgrSingleton->Logout(role_uuid);
}
  
void GuildServiceTimerContext::GuildBuildingUpgrade(rpc::StubCallPtr call, const GuildBuildingUpgradeArg &arg,
      const std::shared_ptr<GuildBuildingUpgradeRes> &res) {
  error_code ec(ErrorCode::ERR_SUCCESS);

  if (!GuildModuleBuildingLogic::BuildingUpgrade(arg.guild_id, arg.building_id, ec)) {
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }

  res->result = static_cast<ErrorCode>(ec.value());
}


};  // namespace guild_service